/**
 * 基于XLSX的Excel数据导入组件
 * @author SPY
 * @description 将excel数据导入到数据库等
 * @date 2020/03/14
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Upload, Button, Icon, message } from 'antd';
import XLSX from 'xlsx';

class ExcelToJson extends Component {

    // 定义传入属性
    static propTypes = {
        idKey: PropTypes.string,  // 映射数据的key
        nameKey: PropTypes.string, // 映射数据的label

        mappingList: PropTypes.array.isRequired, // 映射列表
        isDrag: PropTypes.bool, // 是否支持拖动上传

        onFileChange: PropTypes.func, // 文件发生变化时的回调函数
    }

    // 定义传入属性的默认值
    static defaultProps = {
        idKey: 'key',
        nameKey: 'label',
        mappingList: [],
        isDrag: true,
        onFileChange: () => { },

    }

    // 读取excel文件信息
    handleReadFile = (file) => {
        const { onFileChange } = this.props;
        // 通过FileReader对象读取文件
        const fileReader = new FileReader();
        fileReader.onload = event => {
            try {
                const { result } = event.target;
                // 以二进制流方式读取得到整份excel表格对象
                const workbook = XLSX.read(result, { type: 'binary' });
                // 存储获取到的数据
                let data = {};
                // 遍历每张工作表进行读取（这里默认只读取第一张表）
                for (const sheet in workbook.Sheets) {
                    let tempData = [];
                    // esline-disable-next-line
                    if (workbook.Sheets.hasOwnProperty(sheet)) {
                        // 利用 sheet_to_json 方法将 excel 转成 json 数据
                        data[sheet] = tempData.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
                    }
                }
                const excelData = data[Object.keys(data)[0]];

                const { idKey, nameKey, mappingList } = this.props;
                const excelHeader = [];
                // 获取表头并转换
                for (const headerAttr in excelData[0]) {
                    let dataIndex = mappingList.filter(item => {
                        if (item[nameKey] === headerAttr) return item[idKey];
                    }).shift()[idKey];
                    const header = {
                        title: headerAttr,
                        dataIndex,
                        key: dataIndex
                    };
                    excelHeader.push(header);
                }
                // message.success('上传成功！')
                const newExcelData = [...excelData];
                // 转化Table组件识别的格式：姓名：'王五'=>name:'王五'
                newExcelData.forEach((item) => {
                    mappingList.forEach((p) => {
                        item[p[idKey]] = item[p[nameKey]];
                        delete item[p[nameKey]];
                    });
                });
                if (typeof onFileChange === 'function') onFileChange(newExcelData, excelHeader);
            } catch (e) {
                // 这里可以抛出文件类型错误不正确的相关提示
                console.log(e);
                // message.error('文件类型不正确！');
            }
        }
        // 以二进制方式打开文件
        fileReader.readAsBinaryString(file);
    }

    // 文件上传之前触发的回调函数
    onBeforeUpload = (file) => {
        let fileType;
        if (file && file.name) {
            fileType = file.name.split('.').pop();
        }
        if (['xlsx', 'xls'].indexOf(fileType) < 0) return message.warning('请传入xlsx或xls格式文件');
        this.handleReadFile(file);
    }

    renderUploadPage = () => {
        const { isDrag } = this.props;
        if (isDrag) {
            return (
                <div>
                    <p className="ant-upload-drag-icon">
                        <Icon type="inbox" />
                    </p>
                    <p className="ant-upload-text">上传文件</p>
                    <p className="ant-upload-hint">
                        支持点击或者拖动上传(仅支持xlsx、xls格式文件)
                    </p>
                </div>
            )
        }
        return (
            <div>
                <Button icon='upload' >上传文件</Button>
            </div>
        )
    }

    render() {
        const { isDrag } = this.props;
        const Ud = isDrag ? Upload.Dragger : Upload;

        return (
            <Ud
                beforeUpload={this.onBeforeUpload}
                fileList={[]}
            >
                {this.renderUploadPage()}
            </Ud>
        );
    }
}

export default ExcelToJson;